package com.tang.crm.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tang.crm.dto.CustomerDto;
import com.tang.crm.entity.CusDevPlan;
import com.tang.crm.entity.Customer;
import com.tang.crm.entity.CustomerLoss;
import com.tang.crm.entity.CustomerOrder;
import com.tang.crm.mapper.CustomerMapper;
import com.tang.crm.mapper.CustomerOrderMapper;
import com.tang.crm.service.CustomerLossService;
import com.tang.crm.service.CustomerService;
import com.tang.crm.utils.AssertUtil;
import com.tang.crm.utils.PhoneUtil;
import com.tang.crm.vo.CustomerVo;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.*;

@Service
public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> implements CustomerService {

    @Autowired
    private CustomerMapper customerMapper;

    @Autowired
    private CustomerOrderMapper customerOrderMapper;

    @Autowired
    private CustomerLossService customerLossService;


    /**
     * 多条件分页查询客户 （返回的数据格式必须满足LayUi中数据表格要求的格式）
     * @param customerDto
     * @return
     */
    @Override
    public Map<String, Object> selectAllByParams(CustomerDto customerDto) {
        Map<String, Object> map = new HashMap<>();
        Page<Customer> page = new Page<>(customerDto.getPage(), customerDto.getLimit());
        IPage<Map<String, Object>> mapIPage = customerMapper.selectAllByParams(page, customerDto);
        map.put("code", 0);
        map.put("msg", "");
        map.put("count", mapIPage.getTotal());
        map.put("data", mapIPage.getRecords());
        return map;
    }

    /**
     * 添加客户
     *  1. 参数校验
     *      客户名称 name
     *          非空，名称唯一
     *      法人代表 fr
     *          非空
     *      手机号码 phone
     *          非空，格式正确
     *  2. 设置参数的默认值
     *      是否有效 isValid    1
     *      创建时间 createDate 系统当前时间
     *      修改时间 updateDate 系统当前时间
     *      流失状态 state      0
     *          0=正常客户  1=流失客户
     *      客户编号 khno
     *          系统生成，唯一 （uuid | 时间戳 | 年月日时分秒 | 雪花算法）
     *          格式：KH + 时间戳
     *  3. 执行添加操作，判断受影响的行数
     * @param customer
     */
    @Override
    @Transactional
    public void addCustomer(Customer customer) {
        /* 1. 参数校验 */
        checkParams(customer.getName(), customer.getFr(), customer.getPhone());
        // 判断客户名的唯一性
        AssertUtil.isTrue(null != customerMapper.selectCustomerByName(customer.getName()), "客户名称已存在，请重新输入");

        /* 2.设置参数的默认值 */
        // 是否有效 isValid    1
        customer.setIsValid(1);
        // 创建时间 createDate 系统当前时间
        customer.setCreateDate(new Date());
        // 修改时间 updateDate 系统当前时间
        customer.setUpdateDate(new Date());
        // 流失状态 state  0  0=正常客户  1=流失客户
        customer.setState(0);
        // 客户编号
        String khno = "KH" + System.currentTimeMillis();
        customer.setKhno(khno);

        /* 3. 执行添加操作，判断受影响的行数 */
        AssertUtil.isTrue(customerMapper.insert(customer) != 1, "添加客户信息失败");
    }

    /**
     * 修改客户
     *  1. 参数校验
     *      客户ID id
     *          非空，数据存在
     *      客户名称 name
     *          非空，名称唯一
     *      法人代表 fr
     *          非空
     *      手机号码 phone
     *          非空，格式正确
     *  2. 设置参数的默认值
     *      修改时间 updateDate 系统当前时间
     *  3. 执行更新操作，判断受影响的行数
     * @param customer
     */
    @Override
    @Transactional
    public void updateCustomer(Customer customer) {
        /* 1.参数校验 */
        // 客户ID id 非空，存在
        AssertUtil.isTrue(null == customer.getId(), "待更新记录不存在");
        AssertUtil.isTrue(null == customerMapper.selectById(customer.getId()), "待更新记录不存在");
        checkParams(customer.getName(), customer.getFr(), customer.getPhone());

        /* 2.设置参数的默认值 */
        customer.setUpdateDate(new Date());

        /* 3.执行更新操作，判断受影响的行数 */
        AssertUtil.isTrue(customerMapper.updateById(customer) != 1, "更新客户信息失败");
    }

    /**
     * 删除客户
     *  1. 参数校验
     *      id
     *          非空，数据存在
     *  2. 设置参数默认值
     *      isValid     0
     *      updateDate  系统当前时间
     *  3. 执行删除（更新）操作，判断受影响的行数
     * @param customerId
     */
    @Override
    public void deleteCustomer(Integer customerId) {
        /* 1.参数校验 */
        // id 非空，数据存在
        AssertUtil.isTrue(null == customerId, "待删除记录不存在");
        AssertUtil.isTrue(null == customerMapper.selectById(customerId), "待删除记录不存在");

        /* 2.执行删除操作,判断受影响的行数 */
        AssertUtil.isTrue(customerMapper.deleteById(customerId) != 1, "删除客户信息失败");
    }

    /**
     * 更新客户的流失状态
     *  1. 查询待流失的客户数据
     *  2. 将流失客户数据批量添加到客户流失表中
     *  3. 批量更新客户的流失状态  0=正常客户  1=流失客户
     */
    @Override
    @Transactional
    public void updateCustomerState() {
        /* 1. 查询待流失的客户数据 */
        List<Customer> lossCustomerList = customerMapper.selectLossCustomers();

        /* 2.将流失客户数据批量添加到客户流失表中 */
        // 判断流失客户数据是否存在
        if (lossCustomerList != null && lossCustomerList.size() > 0) {
            // 定义集合 用来接收流失客户的ID
            List<Integer> lossCustomerIds = new ArrayList<>();
            // 定义流失客户的列表
            List<CustomerLoss> customerLossList = new ArrayList<>();
            for (Customer customer : lossCustomerList) {
                // 定义流失客户对象
                CustomerLoss customerLoss = new CustomerLoss();
                // 创建时间  系统当前时间
                customerLoss.setCreateDate(new Date());
                // 客户经理
                customerLoss.setCusManager(customer.getCusManager());
                // 客户名称
                customerLoss.setCusName(customer.getName());
                // 客户编号
                customerLoss.setCusNo(customer.getKhno());
                // 是否有效  1=有效
                customerLoss.setIsValid(1);
                // 修改时间  系统当前时间
                customerLoss.setUpdateDate(new Date());
                // 客户流失状态   0=暂缓流失状态  1=确认流失状态
                customerLoss.setState(0);
                // 客户最后下单时间
                // 通过客户ID查询最后的订单记录（最后一条订单记录）
                CustomerOrder customerOrder = customerOrderMapper.selectLossCustomerOrderByCustomerId(customer.getId());
                // 判断客户订单是否存在，如果存在，则设置最后下单时间
                if (customerOrder != null) {
                    customerLoss.setConfirmLossTime(customerOrder.getOrderDate());
                }
                // 将流失客户对象设置到对应的集合中
                customerLossList.add(customerLoss);
            }
            // 批量添加流失客户记录
            AssertUtil.isTrue(customerLossService.saveBatch(customerLossList), "客户流失数据转移失败");

            /* 3. 批量更新客户的流失状态 */
            AssertUtil.isTrue(customerMapper.updateCustomerStateByIds(lossCustomerIds) != lossCustomerIds.size(), "客户流失数据转移失败");
        }
    }

    /**
     * 查询客户贡献值
     * @param customerDto
     * @return
     */
    @Override
    public Map<String, Object> selectCustomerContributionByParams(CustomerDto customerDto) {
        Map<String, Object> map = new HashMap<>();
        Page<Map<String, Object>> page = new Page<>(customerDto.getPage(), customerDto.getLimit());
        IPage<Map<String, Object>> mapIPage = customerMapper.selectCustomerContributionByParams(page, customerDto);
        map.put("code", 0);
        map.put("msg", "");
        map.put("count", mapIPage.getTotal());
        map.put("data", mapIPage.getRecords());
        return map;
    }

    /**
     * 查询客户构成 （折线图数据处理）
     * @return
     */
    @Override
    public Map<String, Object> countCustomerMake() {
        Map<String, Object> map = new HashMap<>();
        // 查询客户构成数据的列表
        List<Map<String, Object>> dataList = customerMapper.countCustomerMake();
        // 折线图X轴数据  数组
        List<String> dataX = new ArrayList<>();
        // 折线图y轴数据  数组
        List<Integer> dataY = new ArrayList<>();
        if (dataList != null && dataList.size() > 0) {
            for (Map<String, Object> stringObjectMap : dataList) {
                // 获取"level"对应的数据，设置到X轴的集合中
                dataX.add(stringObjectMap.get("level").toString());
                // 获取"total"对应的数据，设置到Y轴的集合中
                dataY.add(Integer.parseInt(stringObjectMap.get("total").toString()));
            }
        }
        map.put("data1", dataX);
        map.put("data2", dataY);
        return map;
    }

    /**
     * 查询客户构成 （饼状图数据处理）
     * @return
     */
    @Override
    public Map<String, Object> countCustomerPieGraph() {
        Map<String, Object> map = new HashMap<>();
        // 查询客户构成数据的列表
        List<Map<String, Object>> dataList = customerMapper.countCustomerMake();
        // 饼状图数据   数组（数组中是字符串）
        List<String> data1 = new ArrayList<>();
        // 折线图y轴数据  数组
        List<Map<String, Object>> data2 = new ArrayList<>();
        if (dataList != null && dataList.size() > 0) {
            for (Map<String, Object> stringObjectMap : dataList) {
                data1.add(stringObjectMap.get("level").toString());
                HashMap<String, Object> hashMap = new HashMap<>();
                hashMap.put("name", stringObjectMap.get("level"));
                hashMap.put("value", stringObjectMap.get("total"));
                data2.add(hashMap);
            }
        }
        map.put("data1", data1);
        map.put("data2", data2);
        return map;
    }

    /**
     *
     * 参数校验
     *      客户名称 name
     *          非空
     *      法人代表 fr
     *          非空
     *      手机号码 phone
     *          非空，格式正确
     * @param customerName
     * @param fr
     * @param phone
     */
    public void checkParams(String customerName, String fr, String phone){
        // 客户名称 name    非空
        AssertUtil.isTrue(StringUtils.isBlank(customerName), "客户名称不能为空");
        // 法人代表 fr      非空
        AssertUtil.isTrue(StringUtils.isBlank(fr), "客户名称不能为空");
        // 手机号码 phone   非空
        AssertUtil.isTrue(StringUtils.isBlank(phone), "手机号不能为空");
        // 手机号码 phone   格式正确
        AssertUtil.isTrue(!PhoneUtil.isMobile(phone),  "手机号码的格式不正确");
    }
}
